package org.kc7bfi.jflac.apps; /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000,2001,2002,2003 Josh Coalson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ import java.io.FileNotFoundException; import java.io.IOException; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import org.kc7bfi.jflac.FrameListener; import org.kc7bfi.jflac.PCMProcessor; import org.kc7bfi.jflac.FLACDecoder; import org.kc7bfi.jflac.frame.Frame; import org.kc7bfi.jflac.io.RandomFileInputStream; import org.kc7bfi.jflac.metadata.Metadata; import org.kc7bfi.jflac.metadata.SeekPoint; import org.kc7bfi.jflac.metadata.SeekTable; import org.kc7bfi.jflac.metadata.StreamInfo; import org.kc7bfi.jflac.util.ByteData; /** * Play a FLAC file application. * @author kc7bfi */ public class SeekTablePlayer implements PCMProcessor, FrameListener { private AudioFormat fmt; private DataLine.Info info; private SourceDataLine line; private StreamInfo streamInfo = null; private SeekTable seekTable = null; /** * Decode and play an input FLAC file. * @param inFileName The input FLAC file name * @param fromSeekPoint The starting Seek Point * @param toSeekPoint The ending Seek Point (non-inclusive) * @throws IOException Thrown if error reading file * @throws LineUnavailableException Thrown if error playing file */ public void play(String inFileName, int fromSeekPoint, int toSeekPoint) throws IOException, LineUnavailableException { System.out.println("Play [" + inFileName + "]"); RandomFileInputStream is = new RandomFileInputStream(inFileName); FLACDecoder decoder = new FLACDecoder(is); decoder.addPCMProcessor(this); decoder.addFrameListener(this); decoder.readMetadata(); // see if SeekTbale exists if (seekTable == null) { System.out.println("Missing SeekTable!"); return; } SeekPoint from = seekTable.getSeekPoint(fromSeekPoint); SeekPoint to = null; if (toSeekPoint + 1 < seekTable.numberOfPoints()) to = seekTable.getSeekPoint(toSeekPoint + 1); System.out.println("Seek From: " + from); System.out.println("Seek To : " + to); decoder.decode(from, to); line.drain(); line.close(); } /** * Process the StreamInfo block. * @param streamInfo the StreamInfo block * @see org.kc7bfi.jflac.PCMProcessor#processStreamInfo(org.kc7bfi.jflac.metadata.StreamInfo) */ public void processStreamInfo(StreamInfo streamInfo) { this.streamInfo = streamInfo; try { fmt = streamInfo.getAudioFormat(); info = new DataLine.Info(SourceDataLine.class, fmt, AudioSystem.NOT_SPECIFIED); line = (SourceDataLine) AudioSystem.getLine(info); line.open(fmt, AudioSystem.NOT_SPECIFIED); line.start(); } catch (LineUnavailableException e) { e.printStackTrace(); } } /** * Process the decoded PCM bytes. * @param pcm The decoded PCM data * @see org.kc7bfi.jflac.PCMProcessor#processPCM(org.kc7bfi.jflac.util.ByteSpace) */ public void processPCM(ByteData pcm) { line.write(pcm.getData(), 0, pcm.getLen()); } /** * Called for each Metadata frame read. * @param metadata The metadata frame read */ public void processMetadata(Metadata metadata) { if (metadata instanceof SeekTable) seekTable = (SeekTable)metadata; } /** * Called for each data frame read. * @param frame The data frame read */ public void processFrame(Frame frame) { } /** * Process a decoder error. * @param msg The error message * @see org.kc7bfi.jflac.FrameListener#processError(java.lang.String) */ public void processError(String msg) { System.out.println("FLAC Error: " + msg); } /** * The main routine. * <p>args[0] is the input file name * @param args Command line arguments */ public static void main(String[] args) { String flacFile = args[0]; int fromSeekPoint = Integer.parseInt(args[1]); int toSeekPoint = Integer.parseInt(args[2]); try { SeekTablePlayer player = new SeekTablePlayer(); player.play(flacFile, fromSeekPoint, toSeekPoint); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (LineUnavailableException e) { e.printStackTrace(); } System.exit(0); } }